import os
import urllib.request
import re,random
from multiprocessing.dummy import Pool as ThreadPool

from bs4 import BeautifulSoup
from bs4.element import Tag

import socks
import socket

from ...core.log.log_go import LogGo
# from ...core.config.global_var import Variables
from ...utility.string.string_go import StringHelper

from stem import Signal
from stem.control import Controller

from urllib.request import urlopen

import requests
import demjson
import time

"""
代理配置
"""
class ProxyHelper(object):
    loops = 1

    # Proxies_http = []
    # Proxies_https = []

    http_proxies_list = []
    https_proxies_list = []

    enable = False # 配置中是否开启代理使用
    configs = None

    header = \
        {
            "User-Agent":
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B329 MicroMessenger/6.5.7"
        }

    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(ProxyHelper, cls).__new__(cls)
            cls.instance.__init()
        return cls.instance

    def __init(self):
        pass
        # if self.enable and len(self.https_proxies_list) < 1:
        #     self.__init_proxy_list()

    @staticmethod
    def init(configs):
        ProxyHelper.configs = configs
        ProxyHelper.enable = configs.proxy_enable
        ProxyHelper().__init_proxy_list()

    def __init_proxy_list(self):
        """初始化 获取 http https 代理"""
        if self.enable:
            if self.configs.proxy_auto_fetch:
                time.sleep(2)
                self.__fetch_proxies(self.configs.proxy_api_http, self.http_proxies_list)
                time.sleep(2)
                self.__fetch_proxies(self.configs.proxy_api_https, self.https_proxies_list)
            else:
                self.http_proxies_list = self.configs.proxies_http_list
                self.https_proxies_list = self.configs.proxies_https_list

            if len(self.http_proxies_list) < 1 or len(self.https_proxies_list) < 1:
                LogGo.error('Init proxy failed!!!!')
                raise Exception('No Proxy !!!')

            LogGo.debug(str(self.http_proxies_list))
            LogGo.debug(str(self.https_proxies_list))

    def __fetch_proxies(self, url, list):
        """
        从蚂蚁代理获取IP 放入 list 中
        :param url:
        :param list:
        :return:
        """
        ProxyHelper.loops += 1

        res = requests.get(url, headers=self.header).text

        if res is not None:

            try:
                json = demjson.decode(res)

                code = json['code']
                data = json['data']
                success = json['success']

                if success:
                    [list.append(str(item['ip']) + ':' + str(item['port'])) for item in data]

                # if len(list) < 1:
                #     raise Exception('Can not get proxy list!')
            except Exception as e:
                LogGo.error(repr(e))
                raise Exception('Can not get proxy list!')
        else:
            raise Exception('Can not get proxy list!')


    # def __fetch_proxies(self, url, list):
    #     """
    #     获取代理数据 放入 list 中
    #     :param url:
    #     :param list:
    #     :return:
    #     """
    #     ProxyHelper.loops += 1
    #     # url = 'http://www.xicidaili.com/nn/'
    #     # url = Variables.proxy_provider
    #     # res = RequestHelper.get(url)
    #
    #     res = requests.get(url, headers=self.header).text
    #
    #     if res is not None:
    #         soup = BeautifulSoup(res, "html.parser")
    #
    #         tag_list = soup.find_all('tr',{'class':'odd'})
    #         ip_list = []
    #
    #         for ip in tag_list:
    #             ip_list.append(ip.contents)
    #
    #         for ip in ip_list:
    #             pair = []
    #             for item in ip:
    #                 if isinstance(item,Tag):
    #                     pair.append(item.get_text())
    #
    #             if pair[8] == '1分钟':
    #                 continue
    #             # if pair[4] != '高匿':
    #             #     continue
    #             proxy = pair[1] + ':' + pair[2]
    #             list.append(proxy)
    #
    #         if len(list) < 1:
    #             if ProxyHelper.loops > 3:
    #                 raise Exception('Can not get proxy')
    #
    #             part = StringHelper.url_divider(url)
    #             part.append(str(ProxyHelper.loops))
    #             url = StringHelper.part_to_url(part)
    #             self.__fetch_proxies(url, list)
    #
    #     else:
    #         LogGo.warning('Get proxies failed!')
    #         raise Exception('Get proxies failed!')

    def get_proxy(self):
        if self.enable:
            if len(self.http_proxies_list) < 1 or len(self.https_proxies_list) < 1:
                LogGo.warning('Proxy Reseting!!!!!!!!')

                self.__init_proxy_list()

            res = dict()
            http = random.choice(self.http_proxies_list)
            https = random.choice(self.https_proxies_list)

            res['http'] = 'http://' + http
            res['https'] = 'http://' + https

            # try:
            #     LogGo.info('proxy ip: ' + res['http'] + '(http)' + ' ' + res['https'] + '(https)' + ' ' + 'local ip: ' + ProxyHelper.check_ip(res))
            # except:
            #     LogGo.warning('proxy error: ' + res['http'] + '(http)' + ' ' + res['https'] + '(https)')
            #
            #     self.http_proxies_list.remove(http)
            #     self.https_proxies_list.remove(https)
            #
            #     return self.get_proxy()

            return res
        else:
            raise Exception("Proxy is not enabled!")

    def reset_proxy(self):
        """
        清空代理池
        :return:
        """
        if self.enable:
            self.http_proxies_list.clear()
            self.https_proxies_list.clear()
            LogGo.info('proxy list clear!')

    @staticmethod
    def check_ip(proxy = None) -> str:
        response = requests.get('http://icanhazip.com/', headers=ProxyHelper.header, proxies=proxy).text
        return str(response)

    @staticmethod
    def where_i_am(func):
        """
        打印 本机ip
        :param func:
        :return:
        """
        def new_func(*args, **args2):
            LogGo.info("Current Ip Address: " + ProxyHelper.check_ip())
            back = func(*args, **args2)
            return back
        return new_func





# def set_proxy(self):
#     """
#     设置代理参数到 RequestHelper 类
#     :return:
#     """
#     if self.enable:
#         proxies_http = ProxyHelper.Proxies_http
#         proxies_https = ProxyHelper.Proxies_https
#
#         if len(proxies_http) > 0:
#             # RequestHelper.proxy_http = random.choice(proxies_http)
#             RequestHelper.proxies['http'] = 'http://' + random.choice(proxies_http)
#             LogGo.info('using http proxy: ' + RequestHelper.proxies['http'])
#
#         if len(proxies_https) > 0:
#             # RequestHelper.proxy_https = random.choice(proxies_https)
#             RequestHelper.proxies['https'] = 'http://' + random.choice(proxies_https)
#             LogGo.info('using https proxy: ' + RequestHelper.proxies['https'])

#
# class TorHelper(object):
#     loops = 1
#
#     Proxies_http = []
#     Proxies_https = []
#
#     open = False # 配置中是否开启代理使用
#
#     controller = None
#
#     def __new__(cls, conf):
#         if not hasattr(cls, 'instance'):
#             cls.instance = super(TorHelper, cls).__new__(cls)
#             cls.config = conf
#             cls.instance.init(conf.proxy_enable)
#         return cls.instance
#
#     def init(self, open:bool):
#         try:
#             self.open = open
#         except Exception as e:
#             LogGo.warning(repr(e))
#             LogGo.warning("Proxy Down!")
#
#     #初始化洋葱路由
#     def set_tor(self):
#         if self.open:
#             # self.controller = Controller.from_port(port=9051)  # ControlPort默认端口9151
#             # self.controller.authenticate()
#             # socks.set_default_proxy(socks.SOCKS5, '127.0.0.1', 9050)
#             # socket.socket = socks.socksocket
#
#             RequestHelper.proxies['http'] = 'socks5://127.0.0.1:9050'
#             RequestHelper.proxies['https'] = 'socks5://127.0.0.1:9050'
#
#             try:
#                 LogGo.info("current ip: " + ProxyHelper.check_ip())
#             except Exception as e:
#                 LogGo.warning(repr(e))
#                 LogGo.warning("Proxy Down!")
#
#     #改变ip
#     def change_tor(self):
#         if self.open:
#             # self.controller.signal(Signal.NEWNYM)  # 更换IP
#             os.system("""(echo authenticate '"129411CF43DC336D608380F77810441E32DC442EEDD7D1F32C15DB36F9"'; echo signal newnym; echo quit) | nc localhost 9051""")
#
#             try:
#                 LogGo.info("proxy ip: " + ProxyHelper.check_ip())
#             except Exception as e:
#                 LogGo.warning(repr(e))
#                 LogGo.warning("Proxy Down!")
#
#     @staticmethod
#     def check_ip() -> str:
#         # response = requests.get('http://icanhazip.com/')
#         # return response.text
#
#         response = RequestHelper.get('http://icanhazip.com/')
#         return str(response)
#
#     @staticmethod
#     def get_proxies(Variables):
#         if Variables.proxy_enable == False:
#             return
#
#         ProxyHelper.loops = 1
#         ProxyHelper.get_proxy_http(Variables.proxy_http_provider,ProxyHelper.Proxies_http)
#         ProxyHelper.get_proxy_http(Variables.proxy_https_provider, ProxyHelper.Proxies_https)
#
#         ProxyHelper.set_proxy()
#
#     @staticmethod
#     def get_proxy_http(url,list, **pars):
#         ProxyHelper.loops += 1
#         # url = 'http://www.xicidaili.com/nn/'
#         # url = Variables.proxy_provider
#         res = RequestHelper.get(url)
#         if res is not None:
#             soup = BeautifulSoup(res, "html.parser")
#
#             tag_list = soup.find_all('tr',{'class':'odd'})
#             ip_list = []
#
#             for ip in tag_list:
#                 ip_list.append(ip.contents)
#
#             for ip in ip_list:
#                 pair = []
#                 for item in ip:
#                     if isinstance(item,Tag):
#                         pair.append(item.get_text())
#
#                 if pair[8] == '1分钟':
#                     continue
#                 # if pair[4] != '高匿':
#                 #     continue
#                 proxy = pair[1] + ':' + pair[2]
#                 list.append(proxy)
#
#             if len(list) < 1:
#                 if ProxyHelper.loops > 3:
#                     raise Exception('Can not get proxy')
#
#                 part = StringHelper.url_divider(url)
#                 part.append(str(ProxyHelper.loops))
#                 url = StringHelper.part_to_url(part)
#                 ProxyHelper.get_proxy_http(url, list)
#
#         else:
#             LogGo.warning('Get proxies failed!')
#             raise Exception('Get proxies failed!')
#
#     @staticmethod
#     def set_proxy():
#         proxies_http = ProxyHelper.Proxies_http
#         proxies_https = ProxyHelper.Proxies_https
#
#         if len(proxies_http) > 0:
#             # RequestHelper.proxy_http = random.choice(proxies_http)
#             RequestHelper.proxies['http'] = 'http://' + random.choice(proxies_http)
#             LogGo.info('using http proxy: ' + RequestHelper.proxies['http'])
#
#         if len(proxies_https) > 0:
#             # RequestHelper.proxy_https = random.choice(proxies_https)
#             RequestHelper.proxies['https'] = 'http://' + random.choice(proxies_https)
#             LogGo.info('using https proxy: ' + RequestHelper.proxies['https'])
#
#     @staticmethod
#     def reset_proxy():
#         RequestHelper.proxies.clear()
#         LogGo.info('proxy clear')
#
#     @staticmethod
#     def where_i_am(func):
#         """
#         打印 本机ip
#         :param func:
#         :return:
#         """
#         def new_func(*args, **args2):
#             LogGo.info("Current Ip Address: " + ProxyHelper.check_ip())
#             back = func(*args, **args2)
#             return back
#         return new_func



